package net.lijingye.education.controller;

import net.lijingye.education.entity.*;
import net.lijingye.education.exception.DaoException;
import net.lijingye.education.exception.FileNotFoundException;
import net.lijingye.education.exception.ObjectNotExistsException;
import net.lijingye.education.request.PostSourceRateRequest;
import net.lijingye.education.request.PostSourceReplyRequest;
import net.lijingye.education.request.PostTopicReplyRequest;
import net.lijingye.education.request.PostTweetReplyRequest;
import net.lijingye.education.response.BaseResponse;
import net.lijingye.education.response.ErrorResponse;
import net.lijingye.education.response.SuccessResponse;
import net.lijingye.education.response.meta.FileNotFoundMeta;
import net.lijingye.education.response.meta.InternalErrorMeta;
import net.lijingye.education.response.meta.JSONParameterErrorMeta;
import net.lijingye.education.response.meta.ObjectNotExistsMeta;
import net.lijingye.education.service.UserService;
import net.lijingye.education.service.UtilService;
import net.lijingye.education.util.CommonUtil;
import net.lijingye.education.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.Valid;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by LijingYe on 2016/3/26.
 */
@RestController
public class UtilController extends BaseController {
    @Autowired
    private UtilService utilService;
    @Autowired
    private UserService userService;

    @RequestMapping(value = "/util/terms", method = RequestMethod.GET)
    public BaseResponse getTerms() {
        try {
            List<TermVO> termVOList = new ArrayList<>();
            List<Term> termList = utilService.getTermList();
            termList.forEach(term -> {
                termVOList.add(new TermVO(term));
            });
            return new SuccessResponse(termVOList);
        } catch (DaoException e) {
            e.printStackTrace();
            return new ErrorResponse(new InternalErrorMeta());
        }
    }

    @RequestMapping(value = "/util/provinces", method = RequestMethod.GET)
    public BaseResponse getProvinces() {
        try {
            List<ProvinceVO> provinceVOList = new ArrayList<>();
            List<Province> provinceList = utilService.getProvinceList();
            provinceList.forEach(province -> {
                provinceVOList.add(new ProvinceVO(province));
            });
            return new SuccessResponse(provinceVOList);
        } catch (DaoException e) {
            e.printStackTrace();
            return new ErrorResponse(new InternalErrorMeta());
        }
    }

    @RequestMapping(value = "/util/provinces/{provinceId}/cities", method = RequestMethod.GET)
    public BaseResponse getProvincesCities(@PathVariable String provinceId) {
        try {
            List<CityVO> cityVOList = new ArrayList<>();
            cityVOList.add(new CityVO("-1", null));
            List<City> cityList = utilService.getCityListByProvinceId(provinceId);
            cityList.forEach(city -> {
                cityVOList.add(new CityVO(city));
            });
            return new SuccessResponse(cityVOList);
        } catch (ObjectNotExistsException e) {
            e.printStackTrace();
            return new ErrorResponse(new ObjectNotExistsMeta());
        } catch (DaoException e) {
            e.printStackTrace();
            return new ErrorResponse(new InternalErrorMeta());
        }
    }

    @RequestMapping(value = "/util/upload", method = RequestMethod.POST)
    public BaseResponse postPic(@RequestParam(value = "file") MultipartFile file) {
        // Static result
        return new SuccessResponse(new FileVO("/test.jpg"));
    }

    @RequestMapping(value = "/util/topics/{topicId}", method = RequestMethod.GET)
    public BaseResponse getTopicDetails(@PathVariable String topicId) throws DaoException {
        try {
            Topic topic = utilService.getTopicByIdAndKick(topicId);
            TopicVO topicVO = new TopicVO(topic);
            return new SuccessResponse(topicVO);
        } catch (ObjectNotExistsException e) {
            System.out.println(e.getMessage());
            return new ErrorResponse(new ObjectNotExistsMeta());
        }
    }

    @RequestMapping(value = "/util/topics/{topicId}/replies", method = RequestMethod.GET)
    public BaseResponse getTopicReplies(@PathVariable String topicId, @RequestParam(value = "page", required = false) String page) throws DaoException {
        try {
            Topic topic = utilService.getTopicById(topicId);
            List<TopicReply> topicReplyList = topic.getTopicReplyList();
            List<TopicReplyVO> topicReplyVOList = new ArrayList<>();
            topicReplyList.forEach(topicReply -> {
                topicReplyVOList.add(new TopicReplyVO(topicReply));
            });
            return CommonUtil.splitPage(topicReplyVOList, page, super.getPageSize());
        } catch (ObjectNotExistsException e) {
            System.out.println(e.getMessage());
            return new ErrorResponse(new ObjectNotExistsMeta());
        }
    }

    @RequestMapping(value = "/util/topics/{topicId}/replies", method = RequestMethod.POST)
    public BaseResponse postTopicReplies(@RequestHeader("Authorization") String accessToken, @PathVariable String topicId, @Valid @RequestBody PostTopicReplyRequest postTopicReplyRequest, BindingResult result) throws DaoException {
        if (result.hasErrors()) {
            return new ErrorResponse(new JSONParameterErrorMeta());
        }
        try {
            User user = userService.getUserByAccessToken(accessToken);
            User toUser;
            if (null == postTopicReplyRequest.getToUserId()) {
                Topic topic = utilService.getTopicById(topicId);
                toUser = topic.getAuthor();
            } else {
                toUser = userService.getUserById(postTopicReplyRequest.getToUserId());
            }
            TopicReply topicReply = utilService.addTopicReply(topicId, new Date(), postTopicReplyRequest.getContent(), user, toUser);
            if (postTopicReplyRequest.getFile().size() > 0) {
                topicReply = utilService.addTopicReplyFile(topicReply.getId(), postTopicReplyRequest.getFile());
            }
            TopicReplyVO topicReplyVO = new TopicReplyVO(topicReply);
            return new SuccessResponse(topicReplyVO);
        } catch (ObjectNotExistsException e) {
            System.out.println(e.getMessage());
            return new ErrorResponse(new ObjectNotExistsMeta());
        }
    }

    @RequestMapping(value = "/util/tweets/{tweetId}", method = RequestMethod.GET)
    public BaseResponse getTweetDetails(@PathVariable String tweetId) throws DaoException {
        try {
            Tweet tweet = utilService.getTweetById(tweetId);
            User user = userService.getUserById(tweet.getUserId());
            TweetVO tweetVO = new TweetVO(tweet, user);
            return new SuccessResponse(tweetVO);
        } catch (ObjectNotExistsException e) {
            System.out.println(e.getMessage());
            return new ErrorResponse(new ObjectNotExistsMeta());
        }
    }

    @RequestMapping(value = "/util/tweets/{tweetId}/replies", method = RequestMethod.GET)
    public BaseResponse getTweetReplies(@PathVariable String tweetId, @RequestParam(value = "page", required = false) String page) throws DaoException {
        try {
            Tweet tweet = utilService.getTweetById(tweetId);
            List<TweetReply> tweetReplyList = tweet.getTweetReplyList();
            List<TweetReplyVO> tweetReplyVOList = new ArrayList<>();
            tweetReplyList.forEach(tweetReply -> {
                tweetReplyVOList.add(new TweetReplyVO(tweetReply));
            });
            return CommonUtil.splitPage(tweetReplyVOList, page, super.getPageSize());
        } catch (ObjectNotExistsException e) {
            System.out.println(e.getMessage());
            return new ErrorResponse(new ObjectNotExistsMeta());
        }
    }

    @RequestMapping(value = "/util/tweets/{tweetId}/replies", method = RequestMethod.POST)
    public BaseResponse postTweetReplies(@RequestHeader("Authorization") String accessToken, @PathVariable String tweetId, @Valid @RequestBody PostTweetReplyRequest postTweetReplyRequest, BindingResult result) throws DaoException {
        if (result.hasErrors()) {
            return new ErrorResponse(new JSONParameterErrorMeta());
        }
        try {
            User user = userService.getUserByAccessToken(accessToken);
            User toUser;
            if (null == postTweetReplyRequest.getToUserId()) {
                Tweet tweet = utilService.getTweetById(tweetId);
                toUser = userService.getUserById(tweet.getUserId());
            } else {
                toUser = userService.getUserById(postTweetReplyRequest.getToUserId());
            }
            TweetReply tweetReply = utilService.addTweetReply(tweetId, new Date(), postTweetReplyRequest.getContent(), user, toUser);
            if (postTweetReplyRequest.getFile().size() > 0) {
                tweetReply = utilService.addTweetReplyFile(tweetReply.getId(), postTweetReplyRequest.getFile());
            }
            TweetReplyVO tweetReplyVO = new TweetReplyVO(tweetReply);
            return new SuccessResponse(tweetReplyVO);
        } catch (ObjectNotExistsException e) {
            System.out.println(e.getMessage());
            return new ErrorResponse(new ObjectNotExistsMeta());
        }
    }

    @RequestMapping(value = "/util/assignments/{assignmentId}", method = RequestMethod.GET)
    public BaseResponse getAssignmentDetails(@RequestHeader("Authorization") String accessToken, @PathVariable String assignmentId) throws DaoException {
        try {
            User user = userService.getUserByAccessToken(accessToken);
            Assignment assignment = utilService.getAssignmentById(assignmentId);
            StudentAssignment studentAssignment = utilService.getStudentAssignmentById(assignment.getId(), user.getId());
            return new SuccessResponse(new AssignmentVO(assignment, studentAssignment));
        } catch (ObjectNotExistsException e) {
            System.out.println(e.getMessage());
            return new ErrorResponse(new ObjectNotExistsMeta());
        }
    }

    @RequestMapping(value = "/util/assignments/{assignmentId}/downloads/solution", method = RequestMethod.GET)
    public BaseResponse getAssignmentSolution(@PathVariable String assignmentId) throws DaoException {
        try {
            Assignment assignment = utilService.getAssignmentByIdAndDownloadAnswer(assignmentId);
            return new SuccessResponse(new FileVO(assignment.getAnswer()));
        } catch (ObjectNotExistsException e) {
            System.out.println(e.getMessage());
            return new ErrorResponse(new ObjectNotExistsMeta());
        } catch (FileNotFoundException e) {
            System.out.println(e.getMessage());
            return new ErrorResponse(new FileNotFoundMeta());
        }
    }

    @RequestMapping(value = "/util/assignments/{assignmentId}/downloads/my", method = RequestMethod.GET)
    public BaseResponse getAssignmentMySolution(@RequestHeader("Authorization") String accessToken, @PathVariable String assignmentId) throws DaoException {
        try {
            User user = userService.getUserByAccessToken(accessToken);
            StudentAssignment studentAssignment = utilService.getStudentAssignmentByIdAndDownload(assignmentId, user.getId());
            return new SuccessResponse(new FileVO(studentAssignment.getMyAnswer()));
        } catch (ObjectNotExistsException e) {
            System.out.println(e.getMessage());
            return new ErrorResponse(new ObjectNotExistsMeta());
        } catch (FileNotFoundException e) {
            System.out.println(e.getMessage());
            return new ErrorResponse(new FileNotFoundMeta());
        }
    }

    @RequestMapping(value = "/util/ppts/{pptId}", method = RequestMethod.GET)
    public BaseResponse getPPTDetails(@PathVariable String pptId) throws DaoException {
        try {
            PPT ppt = utilService.getPPTById(pptId);
            PPTVO pptVO = new PPTVO(ppt);
            return new SuccessResponse(pptVO);
        } catch (ObjectNotExistsException e) {
            System.out.println(e.getMessage());
            return new ErrorResponse(new ObjectNotExistsMeta());
        }
    }

    @RequestMapping(value = "/util/ppts/{pptId}/downloads", method = RequestMethod.GET)
    public BaseResponse getPPTDownload(@PathVariable String pptId) throws DaoException {
        try {
            PPT ppt = utilService.getPPTByIdAndDownload(pptId);
            FileVO fileVO = new FileVO(ppt.getFilePath());
            return new SuccessResponse(fileVO);
        } catch (ObjectNotExistsException e) {
            System.out.println(e.getMessage());
            return new ErrorResponse(new ObjectNotExistsMeta());
        }
    }

    @RequestMapping(value = "/util/sources/{sourceId}", method = RequestMethod.GET)
    public BaseResponse getSourceDetails(@PathVariable String sourceId) throws DaoException {
        try {
            Source source = utilService.getSourceByIdAndKick(sourceId);
            SourceVO sourceVO = new SourceVO(source);
            return new SuccessResponse(sourceVO);
        } catch (ObjectNotExistsException e) {
            System.out.println(e.getMessage());
            return new ErrorResponse(new ObjectNotExistsMeta());
        }
    }

    @RequestMapping(value = "/util/sources/{sourceId}/downloads", method = RequestMethod.GET)
    public BaseResponse getSourceDownload(@PathVariable String sourceId) throws DaoException {
        try {
            Source source = utilService.getSourceByIdAndDownload(sourceId);
            FileVO fileVO = new FileVO(source.getFilePath());
            return new SuccessResponse(fileVO);
        } catch (ObjectNotExistsException e) {
            System.out.println(e.getMessage());
            return new ErrorResponse(new ObjectNotExistsMeta());
        }
    }

    @RequestMapping(value = "/util/sources/{sourceId}/replies", method = RequestMethod.GET)
    public BaseResponse getSourceReplies(@PathVariable String sourceId, @RequestParam(value = "page", required = false) String page) throws DaoException {
        try {
            Source source = utilService.getSourceById(sourceId);
            List<SourceReply> sourceReplyList = source.getSourceReplyList();
            List<SourceReplyVO> sourceReplyVOList = new ArrayList<>();
            sourceReplyList.forEach(sourceReply -> {
                sourceReplyVOList.add(new SourceReplyVO(sourceReply));
            });
            return CommonUtil.splitPage(sourceReplyVOList, page, super.getPageSize());
        } catch (ObjectNotExistsException e) {
            System.out.println(e.getMessage());
            return new ErrorResponse(new ObjectNotExistsMeta());
        }
    }

    @RequestMapping(value = "/util/sources/{sourceId}/replies", method = RequestMethod.POST)
    public BaseResponse postSourceReplies(@RequestHeader("Authorization") String accessToken, @PathVariable String sourceId, @Valid @RequestBody PostSourceReplyRequest postSourceReplyRequest, BindingResult result) throws DaoException {
        if (result.hasErrors()) {
            return new ErrorResponse(new JSONParameterErrorMeta());
        }
        try {
            User user = userService.getUserByAccessToken(accessToken);
            SourceReply sourceReply = utilService.addSourceReply(sourceId, new Date(), postSourceReplyRequest.getContent(), user);
            if (postSourceReplyRequest.getFile().size() > 0) {
                sourceReply = utilService.addSourceReplyFile(sourceReply.getId(), postSourceReplyRequest.getFile());
            }
            SourceReplyVO sourceReplyVO = new SourceReplyVO(sourceReply);
            return new SuccessResponse(sourceReplyVO);
        } catch (ObjectNotExistsException e) {
            System.out.println(e.getMessage());
            return new ErrorResponse(new ObjectNotExistsMeta());
        }
    }

    @RequestMapping(value = "/util/sources/{sourceId}/rates", method = RequestMethod.GET)
    public BaseResponse getSourceRates(@PathVariable String sourceId) throws DaoException {
        try {
            String score = utilService.getSourceAvgScore(sourceId);
            ScoreVO scoreVO = new ScoreVO(score);
            return new SuccessResponse(scoreVO);
        } catch (ObjectNotExistsException e) {
            System.out.println(e.getMessage());
            return new ErrorResponse(new ObjectNotExistsMeta());
        }
    }

    @RequestMapping(value = "/util/sources/{sourceId}/rates/my", method = RequestMethod.GET)
    public BaseResponse getSourceRates(@RequestHeader("Authorization") String accessToken, @PathVariable String sourceId) throws DaoException {
        try {
            User user = userService.getUserByAccessToken(accessToken);
            SourceScore sourceScore = utilService.getSourceMyScore(sourceId, user);
            String score = null == sourceScore ? null : String.valueOf(sourceScore.getScore() + ".0");
            ScoreVO scoreVO = new ScoreVO(score);
            return new SuccessResponse(scoreVO);
        } catch (ObjectNotExistsException e) {
            System.out.println(e.getMessage());
            return new ErrorResponse(new ObjectNotExistsMeta());
        }
    }

    @RequestMapping(value = "/util/sources/{sourceId}/rates", method = RequestMethod.POST)
    public BaseResponse postSourceRates(@RequestHeader("Authorization") String accessToken, @PathVariable String sourceId, @Valid @RequestBody PostSourceRateRequest postSourceRateRequest, BindingResult result) throws DaoException {
        if (result.hasErrors()) {
            return new ErrorResponse(new JSONParameterErrorMeta());
        }
        try {
            User user = userService.getUserByAccessToken(accessToken);
            String score = utilService.addSourceScore(sourceId, user, postSourceRateRequest.getScore());
            ScoreVO scoreVO = new ScoreVO(score);
            return new SuccessResponse(scoreVO);
        } catch (ObjectNotExistsException e) {
            System.out.println(e.getMessage());
            return new ErrorResponse(new ObjectNotExistsMeta());
        }
    }
}
